package com.translate.web.service.impl;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;

import javax.annotation.Resource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.comm.util.contract.IFunction;
import com.common.util.CopyEntity;
import com.common.util.EncryptUtil;
import com.common.util.ListConvertMap;
import com.common.util.MergeDataSource;
import com.common.util.TheMagicSkillOfBeingInvisible;
import com.msg.ResponseCode;
import com.page.PageResponseData;
import com.translate.web.config.contract.IOSSConfig;
import com.translate.web.constant.Const;
import com.translate.web.constant.RedisConstant;
import com.translate.web.constant.RedisExpireTime;
import com.translate.web.dao.UserMapper;
import com.translate.entity.IdAndRecommendName;
import com.translate.entity.TeamAssoc;
import com.translate.entity.TeamInfo;
import com.translate.entity.User;
import com.translate.web.param.contract.ICommonUserByLoginOrRegister;
import com.translate.web.param.contract.IIdAndUserIdParam;
import com.translate.web.param.contract.IJoinTeamParam;
import com.translate.web.param.contract.ILoginParam;
import com.translate.web.param.contract.ILoginParamBySms;
import com.param.contract.IPage;
import com.returns.value.CodeAndData;
import com.returns.value.ICodeAndData;
import com.translate.web.param.contract.IRegisterParamByPhone;
import com.translate.web.param.contract.IRetrievePassword;
import com.translate.web.param.contract.IRetrievePasswordEmail;
import com.translate.web.param.contract.ITeamAddBySearchParam;
import com.translate.web.param.contract.IUpdateEmailParam;
import com.translate.web.param.contract.IUpdatePasswordParam;
import com.translate.web.param.contract.IUserAddParam;
import com.translate.web.param.contract.IUserIdParam;
import com.translate.web.param.contract.IUserSearchByDepartmentParam;
import com.translate.web.param.contract.IWithdrawalAddParam;
import com.translate.web.service.IUserService;
import com.basic.service.impl.BaseServiceImpl;
import com.translate.vo.contract.IFollowPersonVO;
import com.translate.vo.contract.IFollowUpPlanVO;
import com.translate.vo.contract.IUserIdAndNameVO;
import com.translate.vo.contract.IUserVO;

@Service
public class UserServiceImpl extends BaseServiceImpl<User> implements IUserService {

	private IOSSConfig iossConfig;

	public UserServiceImpl(UserMapper mapper) {
		super(mapper);
		// TODO Auto-generated constructor stub
	}

	private RedisTemplate<String, Object> redisTemplate;
	
	private StringRedisTemplate stringRedisTemplate;
	

	@Autowired
	public void setRedisTemplate(RedisTemplate<String, Object> redisTemplate) {
		this.redisTemplate = redisTemplate;
	}

	protected <S extends IPage> String sqlByGetPageListAfterProcesser(S param) {

		String str = ids(param);

		return this.sqlByGetPageList("dept_id in(" + str + ')');
	}

	@Override
	protected Class<User> getEntityClass() {
		// TODO Auto-generated method stub
		return User.class;
	}

	private <S extends IPage> String ids(S param) {
		IUserSearchByDepartmentParam departmentParam = (IUserSearchByDepartmentParam) param;

		StringBuilder stringBuilder = new StringBuilder();

		Integer[] departIds = departmentParam.getDepartIds();

		for (Integer departId : departIds) {
			stringBuilder.append(departId).append(',');
		}

		return stringBuilder.substring(0, stringBuilder.length() - 1);
	}

	protected <VO> void editVO(VO vo, User t) {

//		IUserByDepartVO departVO = (IUserByDepartVO) vo;
//
//		departVO.setId(TheMagicSkillOfBeingInvisible.GetEncodeUserID(departVO.getId()));
	}

	@Override
	protected <S extends IPage> String sqlByGetCounttAfterProcesser(S param) {
		String str = ids(param);

		return this.sqlByGetCount("team_id in(" + str + ')');
	}

	@Override
	public <V> V getUserInfoByModuleUserId(Class<V> targetClass, String userId) {

		User user = this.getUserInfoByModuleUserIdToRedis(userId);

		return CopyEntity.copyEntity(user, targetClass);
	}

	public User getUserInfoByModuleUserIdToRedis(String userId) {

		userId = TheMagicSkillOfBeingInvisible.getDecryptString(userId);

		int id = (int) TheMagicSkillOfBeingInvisible.GetDecodeUserID(Long.valueOf(userId));

		return getUserInfoToCache(id);
	}

	@Override
	public void cleanCurrentUserCache(long userId) {
		this.redisTemplate.delete(RedisConstant.getUserIdKey((int) userId));
	}
	
	public User getUserInfoToCache(int id) {

		String key = RedisConstant.getUserIdKey(id);

		ValueOperations<String, Object> valueOperations = this.redisTemplate.opsForValue();

		User user = (User) valueOperations.get(key);

		if (null != user) {
			return user;
		}

		user = this.selectByPrimaryKey(id);

		if (null == user) {
			user = new User();
		}

		valueOperations.set(key, user, RedisExpireTime.USER_EXPIRE, TimeUnit.SECONDS);

		return user;
	}

	@Override
	public ICodeAndData<User> loginByPwd(ILoginParam loginParam) {

		UserMapper userMapper = this.getBaseMapper();

		User user = userMapper.getUserByEmail(loginParam.getAccount());

		if (null == user) {
			return new CodeAndData<User>(ResponseCode.ERROR_NOT_FOUND_USER, null);
		}

		String pwd = EncryptUtil.getMD5Str(user.getSalt() + loginParam.getPwd() + Const.MD5_STR);

		if (!pwd.equals(user.getPassword())) {
			return new CodeAndData<User>(ResponseCode.ERROR_USER_ACCOUNT_OR_PWD, null);
		}

		return new CodeAndData<User>(ResponseCode.SUCCESS, user);
	}

	protected ICodeAndData<Number> checkSms(String mobile, String code, String key) {

		ValueOperations<String, String> valueOperations = stringRedisTemplate.opsForValue();

		String smsCode = valueOperations.get(key);

		if (null == smsCode) {
			return new CodeAndData<Number>(ResponseCode.SMS_INVALID_ERROR, 0);
		}

		if (!smsCode.equals(code)) {
			return new CodeAndData<Number>(ResponseCode.SMS_CHECK_ERROR, 0);
		}

		return new CodeAndData<Number>(ResponseCode.SUCCESS, 0);
	}

	protected ICodeAndData<Number> checkEmailCode(String email, String code, String key) {

		ValueOperations<String, String> valueOperations = stringRedisTemplate.opsForValue();

		String smsCode = valueOperations.get(key);

		if (null == smsCode) {
			return new CodeAndData<Number>(ResponseCode.EMAIL_INVALID_ERROR, 0);
		}

		if (!smsCode.equals(code)) {
			return new CodeAndData<Number>(ResponseCode.EMAIL_CHECK_ERROR, 0);
		}

		return new CodeAndData<Number>(ResponseCode.SUCCESS, 0);
	}

	@Override
	public ICodeAndData<Number> loginBySms(ILoginParamBySms loginParam) {

		String mobile = loginParam.getMobile();

		String key = RedisConstant.getSmsByKey(mobile);

		ICodeAndData<Number> codeAndData = checkSms(mobile, loginParam.getCode(), key);

		if (0 != codeAndData.getResponseCode().compareTo(ResponseCode.SUCCESS)) {
			return codeAndData;
		}

		UserMapper userMapper = this.getBaseMapper();

		User user = userMapper.loginByMobile(mobile);

		if (null == user) {

			return new CodeAndData<Number>(ResponseCode.ERROR_NOT_FOUND_USER, 0);
		}

		// 删除key
		redisTemplate.delete(key);

		return new CodeAndData<Number>(ResponseCode.SUCCESS, user.getId());
	}

	protected ICodeAndData<Number> checkDataAndPhone(String mobile,
			ICommonUserByLoginOrRegister commonUserByLoginOrRegister, String key) {

		// 短信验证
		ICodeAndData<Number> codeAndData = checkSms(mobile, commonUserByLoginOrRegister.getCode(), key);

		if (0 != codeAndData.getResponseCode().compareTo(ResponseCode.SUCCESS)) {
			return codeAndData;
		}

		// 密码对比

		String pwd = commonUserByLoginOrRegister.getPwd();

		if (!pwd.equals(commonUserByLoginOrRegister.getPwdInputAgin())) {
			return new CodeAndData<Number>(ResponseCode.ERROR_INCONSISTENT_PASSWORDS_FAILURE, 0);
		}

		return null;
	}

	protected ICodeAndData<Number> checkDataAndEmai(String mobile,
			ICommonUserByLoginOrRegister commonUserByLoginOrRegister, String key) {

		// 短信验证
		ICodeAndData<Number> codeAndData = checkEmailCode(mobile, commonUserByLoginOrRegister.getCode(), key);

		if (0 != codeAndData.getResponseCode().compareTo(ResponseCode.SUCCESS)) {
			return codeAndData;
		}

		// 密码对比

		String pwd = commonUserByLoginOrRegister.getPwd();

		if (!pwd.equals(commonUserByLoginOrRegister.getPwdInputAgin())) {
			return new CodeAndData<Number>(ResponseCode.ERROR_INCONSISTENT_PASSWORDS_FAILURE, 0);
		}

		return null;
	}

	@Override
	public ICodeAndData<Number> registerByPhone(IRegisterParamByPhone loginParam) {

		String mobile = loginParam.getPhone();

		String key = RedisConstant.getSmsByKey(mobile);

//		ICodeAndData<Number> codeAndData = this.checkDataAndPhone(mobile, loginParam, key);
//
//		if (null != codeAndData) {
//			return codeAndData;
//		}

		// 删除key
		redisTemplate.delete(key);
		User user = new User();

		user.setUserName(mobile);

		user.setRealname("小清新");

		user.setDescription("然清自有来下");

		user.setEmail(mobile + "@112.com");

		user.setPassword(EncryptUtil.getMD5Str(loginParam.getPwd() + Const.MD5_STR));

		user.setMobile(mobile);

		int res = this.insert(user);

		return new CodeAndData<Number>(ResponseCode.SUCCESS, res);
	}

	protected void insertPropteris(User data) {

		long time = System.currentTimeMillis() / 1000;

		data.setCreateTime(time);

		data.setUpdateTime(time);
	}

	@Override
	@Transactional(propagation = Propagation.MANDATORY)
	public CodeAndData<IdAndRecommendName> registerByEmail(IUserAddParam loginParam) {

		String email = loginParam.getEmail();

		String key = RedisConstant.getEmailKey(email);

//		 邮箱验证
		ICodeAndData<Number> codeAndData = checkEmailCode(email, loginParam.getCode(), key);

		if (0 != codeAndData.getResponseCode().compareTo(ResponseCode.SUCCESS)) {
			return new CodeAndData<IdAndRecommendName>(codeAndData.getResponseCode(), null);
		}

		// 密码对比

		String pwd = loginParam.getPassword();

		if (!pwd.equals(loginParam.getPasswordAgin())) {
			return new CodeAndData<IdAndRecommendName>(ResponseCode.ERROR_INCONSISTENT_PASSWORDS_FAILURE, null);
		}

		redisTemplate.delete(key);

		ICodeAndData<User> recommend = this.parseRecommendCode(loginParam);

		ResponseCode responseCode = recommend.getResponseCode();

		if (!responseCode.equals(ResponseCode.SUCCESS)) {
			return new CodeAndData<IdAndRecommendName>(responseCode, null);
		}

		User data = recommend.getData();

		User user = CopyEntity.copyEntity(loginParam, User.class);

		user.setUserName(email.substring(0, email.indexOf('@')));

		long salt = System.currentTimeMillis() / 1000;
		user.setSalt("" + salt);

		IdAndRecommendName recommendName = new IdAndRecommendName();
		
		if (null != data) {
			user.setRecommendedUserId(data.getId());
			recommendName.setRecommendName(data.getRealname());
		}
		
		user.setBirthday(0L);
		
		user.setTeamId(0);
		
		user.setStatus((byte) 0);
		user.setPassword(EncryptUtil.getMD5Str(salt + pwd + Const.MD5_STR));
		try {
			this.insert(user);
		} catch (Exception e) {
			return new CodeAndData<>("邮箱已注册", 500);
		}
		
		
		recommendName.setId(user.getId().intValue());

		return new CodeAndData<IdAndRecommendName>(ResponseCode.SUCCESS, recommendName);
	}

	/**
	 * 处理推荐码
	 * 
	 * @param loginParam
	 * @return
	 */
	private ICodeAndData<User> parseRecommendCode(IUserAddParam loginParam) {

		// 处理推荐码

		String recommendedCode = loginParam.getRecommendedCode();

		if (null == recommendedCode) {

			return new CodeAndData<User>(ResponseCode.SUCCESS, null);
		}

		User user = ((UserMapper) this.getBaseMapper()).getUserByRecommendedCode(Integer.valueOf(recommendedCode));

		if (null == user) {
			return new CodeAndData<User>(ResponseCode.EMAIL_RECOMMEND_ERROR, null);
		}

		return new CodeAndData<User>(ResponseCode.SUCCESS, user);
	}

	@Override
	public ICodeAndData<Number> retrievePasswordByPhone(IRetrievePassword loginParam) {
		String mobile = loginParam.getPhone();

		String key = RedisConstant.getSmsByKey(mobile);

		ICodeAndData<Number> codeAndData = this.checkDataAndPhone(mobile, loginParam, key);
//
		if (null != codeAndData) {
			return codeAndData;
		}

		// 删除key
		redisTemplate.delete(key);

		UserMapper userMapper = this.getBaseMapper();

		int res = userMapper.updatePwdByMobilePhone(mobile, EncryptUtil.getMD5Str(loginParam.getPwd() + Const.MD5_STR));

		return new CodeAndData<Number>(ResponseCode.SUCCESS, res);
	}

	@Override
	@Transactional
	public ICodeAndData<Number> retrievePasswordByEmail(IRetrievePasswordEmail paramByEmail) {
		String email = paramByEmail.getEmail();

		String key = RedisConstant.getEmailKey(email);

		ICodeAndData<Number> codeAndData = this.checkDataAndEmai(email, paramByEmail, key);

		if (null != codeAndData) {
			return codeAndData;
		}

		// 删除key
		redisTemplate.delete(key);

		UserMapper userMapper = this.getBaseMapper();

		User userByEmail = userMapper.getUserByEmailForUpdate(email);

		long timeMillis = System.currentTimeMillis();
		userByEmail.setSalt(timeMillis + "");

		userByEmail.setPassword(EncryptUtil.getMD5Str(timeMillis + paramByEmail.getPwd() + Const.MD5_STR));

		int res = userMapper.updateByPrimaryKeySelective(userByEmail);

		return new CodeAndData<Number>(ResponseCode.SUCCESS, res);
	}

	@Override
	public boolean checkUserExits(String account) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public <VO extends IFollowPersonVO> List<VO> getUserList(Integer[] customerId, Class<VO> target) {

		List<User> users = this.usersToCache(customerId);

		VO vo;

		List<VO> vos = new ArrayList<>();
		try {
			for (User user : users) {

				vo = target.newInstance();

				vo.setUserId(TheMagicSkillOfBeingInvisible.GetEncodeUserID(user.getId()));

				vo.setUserName(user.getUserName());

				vos.add(vo);
			}

			return vos;

		} catch (Exception e) {

			e.printStackTrace();
		}

		return vos;
	}

	/**
	 * 把用户数据导入到缓存中
	 * 
	 * @param ids
	 * @return
	 */
	protected List<User> usersToCache(Integer[] ids) {

		if (0 == ids.length) {
			return new ArrayList<>(0);
		}

		String key = RedisConstant.getKeyByUserIds(ids);

		ValueOperations<String, Object> operations = this.redisTemplate.opsForValue();

		List<User> users = (List<User>) operations.get(key);

		if (null != users) {
			return users;
		}

		users = this.getDataByIds(ids);

		if (null == users) {
			users = new ArrayList<>();

			operations.set(key, users, 5, TimeUnit.SECONDS);

			return users;
		}

		operations.set(key, users, 15, TimeUnit.SECONDS);

		return users;

	}

	public List<User> getDataByIdsMergeVO(Integer[] ids) {
		return this.usersToCache(ids);
	}

	@Override
	public <VO> List<VO> getUserList(List<VO> vos) {

		Function<VO, Integer> function = e -> ((IFollowUpPlanVO) e).getCreateUserId();

		Integer[] ids = vos.stream().map(e -> function.apply(e)).toArray(Integer[]::new);

		List<User> list = this.usersToCache(ids);

		Map<Long, User> map = ListConvertMap.listToMap(list, User::getId);

		MergeDataSource<VO> dataSource = new MergeDataSource<>(vos);

		Function<VO, Long> mergeFunction = e -> (long) ((IFollowUpPlanVO) e).getCreateUserId();

		dataSource.merge(mergeFunction, map, new IFunction<VO, VO>() {

			@Override
			public <K, V> VO apply(VO t, V v) {

				IFollowUpPlanVO followUpPlanVO = (IFollowUpPlanVO) t;

				User user = (User) v;

				followUpPlanVO.setCreateUserName(user.getRealname());

				return t;
			}
		});

		return vos;
	}

	@Override
	public <VO> List<User> getDataByIdsMergeVO(List<VO> vos, Function<VO, Integer> function) {

		Integer[] ids = vos.stream().map(e -> function.apply(e)).toArray(Integer[]::new);

		return this.getDataByIdsMergeVO(ids);
	}

	@Override
	public <VO extends IUserIdAndNameVO> List<VO> getDataByIdsMergeVO(Integer[] ids, Class<VO> target) {

		List<User> list = this.usersToCache(ids);

		List<VO> vos = new ArrayList<>(ids.length * 4 / 3);

		VO vo;
		try {
			for (User user : list) {

				vo = target.newInstance();

				vo.setId((int) TheMagicSkillOfBeingInvisible.GetEncodeUserID(user.getId()));

				vo.setUserName(user.getRealname());

				vos.add(vo);
			}
		} catch (Exception e) {
			// TODO: handle exception
		}

		return vos;
	}

	@Override
	public <VO extends IUserVO> IUserVO getUserDetails(int userId, Class<VO> target) {

		User user = this.getUserInfoToCache(userId);

		IUserVO userVO = CopyEntity.copyEntity(user, target);

		String avatar = userVO.getAvatar();

		if (null == avatar) {
			return userVO;
		}

		userVO.setAvatar(this.iossConfig.getLocalPicURL().concat(avatar));

		return userVO;
	}

	@Autowired
	public void setIossConfig(IOSSConfig iossConfig) {
		this.iossConfig = iossConfig;
	}

	@Override
	@Transactional(propagation = Propagation.MANDATORY)
	public int updateDiscount(long id, BigDecimal reward) {
		User user = new User();
		user.setId(id);
		user.setDiscount(reward);
		int res = this.mapper.updateByPrimaryKeySelective(user);

		String key = RedisConstant.getUserIdKey((int) id);

		this.redisTemplate.delete(key);

		return res;
	}

	@Override
	@Transactional(propagation = Propagation.MANDATORY)
	public User selectDuplicateCheckCoupon(int id) {

		UserMapper userMapper = this.getBaseMapper();

		return userMapper.selectDuplicateCheckCoupon(id);
	}

	@Override
	public int joinTeam(IJoinTeamParam param) {

		UserMapper userMapper = this.getBaseMapper();
		
		param.setJoinTime(System.currentTimeMillis() / 1000);

		return userMapper.joinTeam(param);
	}

//	@Override
//	protected String getAssocKey() {
//		// TODO Auto-generated method stub
//		return "team_id";
//	}

	@Override
	public <VO extends IUserVO> ICodeAndData<PageResponseData<VO>> getTeamList(IUserIdParam param, Class<VO> target) {

		return parseUserList(param, target, 1);
	}

	private <VO extends IUserVO> ICodeAndData<PageResponseData<VO>> parseUserList(IUserIdParam param, Class<VO> target,
			int status) {
		User userInfoToCache = this.getUserInfoToCache(param.getUserId());

		if (0 == userInfoToCache.getIsRegimental()) {
			return new CodeAndData<PageResponseData<VO>>("您不是团长，无法查看团队成员", 500, null);
		}

		IPage page = (IPage) param;

		int pageNum = page.getPageNum();

		param.setStatus(status);

		Integer teamId = userInfoToCache.getTeamId();

		if (1 == pageNum) {
			int maxId = this.getMaxId(" where team_id = " + teamId);

//			int lastId = (maxId + pageNum -1) / pageNum;

			int lastId = (maxId) / pageNum;

			page.setLastId(lastId);
		}

		param.setUserId(teamId);

		PageResponseData<VO> dataByList = this.getDataByListBySearch((IPage) page, target);
		return new CodeAndData<PageResponseData<VO>>(dataByList);
	}

	@Override
	public <VO extends IUserVO> ICodeAndData<PageResponseData<VO>> applyForTeamList(IUserIdParam page,
			Class<VO> target) {

		User userInfoToCache = this.getUserInfoToCache(page.getUserId());

		if (0 == userInfoToCache.getIsRegimental()) {
			return new CodeAndData<PageResponseData<VO>>("您不是团长，无法查看团队成员", 500, null);
		}

		return parseUserList(page, target, 0);

	}

	@Override
	public ICodeAndData<Integer> passThrough(IIdAndUserIdParam param) {

		ICodeAndData<Integer> validateTeam = validateTeam(param);

		if (ResponseCode.SUCCESS.getCode() != validateTeam.getStatus()) {
			return validateTeam;
		}

		UserMapper userMapper = this.getBaseMapper();
		
		User user = new User();
		
		user.setId(param.getId().longValue());
		user.setJoinTime(System.currentTimeMillis() / 1000);
		

		return new CodeAndData<Integer>(userMapper.passThrough(user));
	}

	private ICodeAndData<Integer> validateTeam(IIdAndUserIdParam param) {
		User userInfoToCache = this.getUserInfoToCache((int) param.getUserId());

		if (0 == userInfoToCache.getIsRegimental()) {
			return new CodeAndData<Integer>("您不是团长，无法查看团队成员", 500, null);
		}

		User teamMember = this.getUserInfoToCache(param.getId());

		if (null == teamMember) {
			return new CodeAndData<Integer>("用户不存在", 500, null);
		}

		if (userInfoToCache.getTeamId().intValue() != teamMember.getTeamId().intValue()) {
			return new CodeAndData<Integer>("不属于您的团队", 500, null);
		}
		return new CodeAndData<Integer>(teamMember.getTeamId());
	}

	@Override
	public ICodeAndData<Integer> refuse(IIdAndUserIdParam param) {
		ICodeAndData<Integer> validateTeam = validateTeam(param);

		if (ResponseCode.SUCCESS.getCode() != validateTeam.getStatus()) {
			return validateTeam;
		}

		UserMapper userMapper = this.getBaseMapper();

		userMapper.refuse(param);
		return validateTeam;
	}

	@Override
	public ICodeAndData<Integer> removeMemberByTeam(IIdAndUserIdParam param) {
		ICodeAndData<Integer> validateTeam = validateTeam(param);

		if (ResponseCode.SUCCESS.getCode() != validateTeam.getStatus()) {
			return validateTeam;
		}

		UserMapper userMapper = this.getBaseMapper();

		userMapper.removeMemberByTeam(param.getId());
		return validateTeam;
	}

	@Override
	@Transactional(propagation = Propagation.MANDATORY)
	public ICodeAndData<Integer> addTeamMember(ITeamAddBySearchParam param) {

		int userId = (int) param.getUserId();
		User userInfoToCache = this.getUserInfoToCache((int) userId);

		if (0 == userInfoToCache.getIsRegimental()) {
			return new CodeAndData<Integer>("您不是团长，无法查看团队成员", 500, null);
		}

		UserMapper userMapper = this.getBaseMapper();

		User searchTeamMember = userMapper.searchTeamMember(param);

		if (null == searchTeamMember) {
			return new CodeAndData<Integer>("找不到该用户", 500, null);
		}

		if (0 != searchTeamMember.getTeamId()) {
			return new CodeAndData<Integer>("该用户已加入该或其他团队", 500, null);
		}

		int directlyThrough = userMapper.
				directlyThrough(searchTeamMember.getId(), userInfoToCache.getTeamId(), System.currentTimeMillis() / 1000);

		return new CodeAndData<Integer>(directlyThrough);
	}

	@Override
	public ICodeAndData<Integer> exitTeam(int id) {

		User userInfoToCache = this.getUserInfoToCache(id);

		if (0 != userInfoToCache.getIsRegimental()) {
			return new CodeAndData<Integer>("您是团长，", 500, null);
		}

		UserMapper userMapper = this.getBaseMapper();

		return new CodeAndData<Integer>(userMapper.removeMemberByTeam(id));

	}

	@Override
	public List<User> getUserIdsByRealname(String realname) {

		UserMapper userMapper = this.getBaseMapper();

		return userMapper.getUserIdsByRealname(realname);

	}

	@Override
	public ICodeAndData<Integer> updatePassword(IUpdatePasswordParam param) {

		int userId = param.getUserId();
		User user = this.getUserInfoToCache(userId);

		String pwd = EncryptUtil.getMD5Str(user.getSalt() + param.getPwd() + Const.MD5_STR);

		if (!pwd.equals(user.getPassword())) {
			return new CodeAndData<Integer>("原密码与当前用户密码不一致", 500);
		}

		long timeMillis = System.currentTimeMillis();

		String newPwd = EncryptUtil.getMD5Str(timeMillis + param.getPwdInputAgin() + Const.MD5_STR);

		User upUser = new User();

		upUser.setPassword(newPwd);

		upUser.setSalt(timeMillis + "");

		upUser.setId((long) userId);

		return new CodeAndData<Integer>(mapper.updateByPrimaryKeySelective(upUser));
	}

	@Override
	public List<TeamAssoc> getTeamAssocs(int[] teamIds) {

		UserMapper userMapper = this.getBaseMapper();

		return userMapper.staticesCount(teamIds);
	}

	@Override
	public List<TeamInfo> groupNumAndApplyNum(int teamId) {

		UserMapper userMapper = this.getBaseMapper();

		return userMapper.groupNumAndApplyNum(teamId);

	}

	@Override
	public ICodeAndData<Integer> checkEmail(IUpdateEmailParam updateEmailParam) {

		String code = updateEmailParam.getCode();

		ValueOperations<String, String> opsForValue = stringRedisTemplate.opsForValue();

		String key = RedisConstant.getEmailKey(updateEmailParam.getEmail());
		
		String object = opsForValue.get(key);

		if (null == object || !object.equals(code)) {
			return new CodeAndData<Integer>("验证码错误", 500);
		}
		
		User userInfoToCache = this.getUserInfoToCache(updateEmailParam.getUserId());
		
		if (null == userInfoToCache) {
            return new CodeAndData<Integer>("用户不存在", 500);
        }
		
		if (!userInfoToCache.getEmail().equals(updateEmailParam.getEmail())) {
            return new CodeAndData<Integer>("该邮箱与原邮箱不一致", 500);
        }
		
		return new CodeAndData<Integer>("成功", 200);
	}

	@Override
	public ICodeAndData<Integer> updateEmail(IUpdateEmailParam updateEmailParam) {

		String email = updateEmailParam.getEmail();

		String code = updateEmailParam.getCode();

		String key = RedisConstant.getEmailKey(email);

		ValueOperations<String, String> opsForValue = stringRedisTemplate.opsForValue();

		String object =  opsForValue.get(key);

		if (null == object|| !object.toString().equals(code)) {
			return new CodeAndData<Integer>("验证码错误", 500);
		}

		User user = new User();

		user.setId((long) updateEmailParam.getUserId());

		user.setEmail(email);

		//对比一下邮箱是否已经存在
		UserMapper userMapper = this.getBaseMapper();

		User usernew = userMapper.getUserByEmail(email);
		if (null != usernew) {
			return  new CodeAndData<Integer>("该邮箱已注册", 500);
		}
		mapper.updateByPrimaryKeySelective(user);

		return new CodeAndData<Integer>(1);

	}

	@Override
	@Transactional(propagation = Propagation.MANDATORY)
	public int exchangeAcademicCoins(IWithdrawalAddParam param) {

		long userId = param.getUserId();
		User selectByPrimaryKey = this.selectByPrimaryKey((int) userId);

		User user = new User();

		user.setId(userId);
		user.setAcademicCurrency(selectByPrimaryKey.getAcademicCurrency().add(param.getAmount()));

		int updateByPrimaryKeySelective = this.updateByPrimaryKeySelective(user);
		
		cleanCurrentUserCache(userId);
		
		
		return updateByPrimaryKeySelective;
	}
	
	protected String getAssocKey() {
		return "id";
	}

	@Override
	public <DATA> List<DATA> staticsTeamInfo(int teamId) {
		
		UserMapper userMapper = this.getBaseMapper();
		
		return userMapper.staticsTeamInfo(teamId);
	}

	@Override
	public List<User> getUserIdsBySearchName(String userName) {
		
		UserMapper userMapper = this.getBaseMapper();
		
		return userMapper.getUserIdsBySearchName(userName);
	}

	@Override
	public int countRecomendNum(long recommendId) {
		UserMapper userMapper = this.getBaseMapper();
		
		return userMapper.countRecomendNum(recommendId);
	}
	
	@Resource
	public void setStringRedisTemplate(StringRedisTemplate stringRedisTemplate) {
		this.stringRedisTemplate = stringRedisTemplate;
	}
}